package fem2;

import fem2.analysis.Analysis;
import fem2.analysis.LinearStaticAnalysis;
import fem2.analysis.NonlinearStaticAnalysis;
import fem2.analysis.NonlinearStaticManualAnalysis;
import fem2.enu.EchoLevelType;
import fem2.observer.TimeStepObserver;
import fem2.strategies.Strategy;

/**
 * 
 * @author hbui
 * 
 */
public abstract class AbstractDemoWithGiD {

	protected String projectDir;
	protected String projectName;
	protected String meshFileName;

	/**
	 * create the mesh
	 * 
	 * @return
	 */
	public abstract Mesh createMesh();

	/**
	 * add loads to model
	 * 
	 * @param m
	 * @return
	 */
	public abstract Model createConditions(Model m);

	/**
	 * 
	 * @return
	 */
	public abstract Model createModel();

	/**
	 * 
	 * @param m
	 * @param s
	 * @param o
	 */
	public abstract void addObservers(Model m, Strategy s, TimeStepObserver o);

	/**
	 * perform a 1-step analysis
	 */
	public void run() {
		Model m = createModel();

		Analysis an = new LinearStaticAnalysis(m);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	/**
	 * perform multi-step analysis
	 * 
	 * @param nt
	 */
	public void run(int nt) {
		Model m = createModel();

		Analysis an = new NonlinearStaticAnalysis(m, nt);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	/**
	 * perform analysis with prescribed lambda
	 * 
	 * @param lambda
	 */
	public void run(double[] lambda) {
		Model m = createModel();

		Analysis an = new NonlinearStaticManualAnalysis(m, lambda, lambda);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	/**
	 * post process by prinout nodal values
	 * 
	 * @param m
	 */
	public void postProcess(Model m) {

		Mesh mesh = m.getMesh();
		for (int i = 0; i < mesh.countNodes(); i++) {
			Node n = mesh.getNode(i);
			Debugger.watch("n" + n.getId() + ": ", n.getUHatLocal());
		}

		Debugger.watch("Analysis completed");
	}
}
